#include "chessboard.h"
#include <QPixmap>
#include <QDebug>

// 构造函数
ChessBoard::ChessBoard(QWidget *parent) : QLabel(parent)
{
    // 模拟棋盘 和 棋子图标的初始化
    for(int i=0; i<MAXSIZE; i++)
    {
        for(int j=0; j<MAXSIZE; j++)
        {
            chess[i][j] = new QLabel(this);
            chess[i][j]->setScaledContents(true);
            chess[i][j]->resize(25,25);
            chess[i][j]->move(30*i, 30*j);

            table[i][j] = 0;
        }
    }

    // 棋盘背景设置
    this->setScaledContents(true);
    this->resize(446, 446);
    QPixmap pix;
    pix.load(":/res/qipan.png");
    this->setPixmap(pix);

    // 其他数据初始化
    game_start = false;     // 初始设定为游戏未开始
    cur_player = 0;         // 设定先手棋子 为空时谁手快谁先手
    sound_chess = new QSound(":/res/xiaqi.wav", this);  // 添加落子音效
    sound_chess->setLoops(1);                           // 设置音效循环次数
}

// 析构函数
ChessBoard::~ChessBoard()
{
    for(int i=0; i<MAXSIZE; i++)
    {
        for(int j=0; j<MAXSIZE; j++)
        {
            delete chess[i][j];
        }
    }
    delete sound_chess;
}

// 重写 鼠标按下事件
void ChessBoard::mousePressEvent(QMouseEvent *ev)
{
    // 计算按下坐标对应二维数组中的位置
    int row = ev->x()/30;
    int col = ev->y()/30;

    // 判断该位置是否可以落子
    if(game_start && (table[row][col] == 0))    // 只有当游戏已经开始 并且所点击位置未落子才可以
    {
        int pos[2];
        pos[0] = row;
        pos[1] = col;
        emit pos_press(pos);    // 发出信号 并传递该坐标(在二维数组中的位置)
    }
}

// 设定游戏是否开始
void ChessBoard::setGame_start(bool newGame_start)
{
    game_start = newGame_start;
}

// 在指定位置落下指定类型的棋子 若不是当前玩家回合则不落子
bool ChessBoard::set_chess(int row, int col, int chess_type)
{
    if(cur_player == 0)             // 刚刚开始游戏 谁手快谁先手
    {
        cur_player = chess_type;
    }

    if(chess_type != cur_player)    // 当前不是你的回合 不允许落子
        return true;                // 游戏还在进行 未分出胜负

    // 落子 根据棋子类型加载相应图片
    QPixmap pix;
    if(chess_type == WHITE)
    {
        pix.load(":/res/baizi.png");
    }
    else if(chess_type == BLACK)
    {
        pix.load(":/res/heiqi.png");
    }
    chess[row][col]->setPixmap(pix);
    // 模拟棋盘的数组中也相应修改
    table[row][col] = chess_type;

    // 发出落子音效
    sound_chess->play();

    // 落子后立即判断是否分出胜负 若分出胜负则立即结束游戏 否则继续
    if(judgment())
    {
        game_start = false;
        return false;   // 结束游戏 cur_player 赢得本局游戏
    }
    // 落子完成 且未分出胜负换边
    cur_player = -chess_type;
    return true;
}

// 重置整个棋盘 所有数据初始化
void ChessBoard::reset_board()
{
    game_start = true;
    cur_player = 0;
    QPixmap pix;
    pix.load(NULL);

    for(int i=0; i<MAXSIZE; i++)
    {
        for(int j=0; j<MAXSIZE; j++)
        {
            table[i][j] = 0;
            chess[i][j]->setPixmap(pix);
        }
    }
}

// 判断(x,y)位置起始的8个方向上有没有五子连珠
bool ChessBoard::test(int x, int y)
{
    int i, j;
    int sum = 0;    // sum为连成一列的棋子数量 sum==5时则返回true

    // 向上
    if(x >= 4)
    {
        sum = 0;
        for(i=x, j=y; i>=0; i--)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    // 右上
    if(x >= 4 && y <= MAXSIZE-5)
    {
        sum = 0;
        for(i=x, j=y; i>=0 && j<MAXSIZE; i--, j++)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    // 向右
    if(y <= MAXSIZE-5)
    {
        sum = 0;
        for(i=x, j=y; j<MAXSIZE; j++)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    // 右下
    if(x <= MAXSIZE-5 && y <= MAXSIZE-5)
    {
        sum = 0;
        for(i=x, j=y; i<MAXSIZE && j<MAXSIZE; i++, j++)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    // 向下
    if(x <= MAXSIZE-5)
    {
        sum = 0;
        for(i=x, j=y; i<MAXSIZE; i++)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    // 左下
    if(x <= MAXSIZE-5 && y >= 4)
    {
        sum = 0;
        for(i=x, j=y; i<MAXSIZE && j>=0; i++, j--)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    // 向左
    if(y >= 4)
    {
        sum = 0;
        for(i=x, j=y; j>=0; j--)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    // 左上
    if(x >= 4 && y >= 4)
    {
        sum = 0;
        for(i=x, j=y; i>=0 && j>=0; i--, j--)
        {
            if(table[i][j] == cur_player)
            {
                sum++;
                if(sum == 5)
                {
                    return true;
                }
            }
            else
            {
                break;
            }
        }
    }
    return false;
}
// 判断当前回合的玩家有没有五子连珠
bool ChessBoard::judgment()
{
    int i, j;
    // 逐一验证 验证过的临时修改为USED
    for(i=0; i<MAXSIZE; i++)
    {
        for(j=0; j<MAXSIZE; j++)
        {
            if(table[i][j] == cur_player)
            {
                if(test(i,j))
                {
                    return true;
                }
                else
                {
                    table[i][j] = USED;
                }
            }
        }
    }

    // 将修改过的还原
    for(i=0; i<MAXSIZE; i++)
    {
        for(j=0; j<MAXSIZE; j++)
        {
            if(table[i][j] == USED)
            {
                table[i][j] = cur_player;
            }

        }
    }
    return false;
}

// 查找(x,y)位置起始最适合chess_type落子的位置 并返回最大连子数目
int ChessBoard::find(int x, int y, int &row, int &col, int chess_type)
{
    int i, j;
    int sum = 0;    // sum为连成一列的棋子数量
    int tmp = 0;

    // 向上
    if(x >= 4)
    {
        tmp = 0;
        for(i=x, j=y; i>=0; i--)
        {
            if(table[i][j] == chess_type)    // chess为对方棋子
            {
                tmp++;                  // 连子数目加一
            }
            else if(table[i][j] == 0)   // 该位置为空可以考虑落子
            {
                if(sum < tmp)           // 若连子数目更大则暂定在此落子
                {
                    sum = tmp;          // 更新落子位置的最大连子数目
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    // 右上
    if(x >= 4 && y <= MAXSIZE-5)
    {
        tmp = 0;
        for(i=x, j=y; i>=0 && j<MAXSIZE; i--, j++)
        {
            if(table[i][j] == chess_type)
            {
                tmp++;
            }
            else if(table[i][j] == 0)
            {
                if(sum < tmp)
                {
                    sum = tmp;
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    // 向右
    if(y <= MAXSIZE-5)
    {
        tmp = 0;
        for(i=x, j=y; j<MAXSIZE; j++)
        {
            if(table[i][j] == chess_type)
            {
                tmp++;
            }
            else if(table[i][j] == 0)
            {
                if(sum < tmp)
                {
                    sum = tmp;
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    // 右下
    if(x <= MAXSIZE-5 && y <= MAXSIZE-5)
    {
        tmp = 0;
        for(i=x, j=y; i<MAXSIZE && j<MAXSIZE; i++, j++)
        {
            if(table[i][j] == chess_type)
            {
                tmp++;
            }
            else if(table[i][j] == 0)
            {
                if(sum < tmp)
                {
                    sum = tmp;
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    // 向下
    if(x <= MAXSIZE-5)
    {
        tmp = 0;
        for(i=x, j=y; i<MAXSIZE; i++)
        {
            if(table[i][j] == chess_type)
            {
                tmp++;
            }
            else if(table[i][j] == 0)
            {
                if(sum < tmp)
                {
                    sum = tmp;
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    // 左下
    if(x <= MAXSIZE-5 && y >= 4)
    {
        tmp = 0;
        for(i=x, j=y; i<MAXSIZE && j>=0; i++, j--)
        {
            if(table[i][j] == chess_type)
            {
                tmp++;
            }
            else if(table[i][j] == 0)
            {
                if(sum < tmp)
                {
                    sum = tmp;
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    // 向左
    if(y >= 4)
    {
        tmp = 0;
        for(i=x, j=y; j>=0; j--)
        {
            if(table[i][j] == chess_type)
            {
                tmp++;
            }
            else if(table[i][j] == 0)
            {
                if(sum < tmp)
                {
                    sum = tmp;
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    // 左上
    if(x >= 4 && y >= 4)
    {
        tmp = 0;
        for(i=x, j=y; i>=0 && j>=0; i--, j--)
        {
            if(table[i][j] == chess_type)
            {
                tmp++;

            }
            else if(table[i][j] == 0)
            {
                if(sum < tmp)
                {
                    sum = tmp;
                    row = i;
                    col = j;
                }
                break;
            }
            else
                break;
        }
    }
    return sum;
}

// 用于AI查找下一步落子的位置
void ChessBoard::findPos(int &row, int &col, int chess_type)
{
    int sum = 0;
    int tmp = 0;
    row = 0;
    col = 0;
    for(int i=0; i<MAXSIZE; i++)
    {
        for(int j=0; j<MAXSIZE; j++)
        {
            if(table[i][j] == (-chess_type))
            {

                int tmp_row, tmp_col;
                tmp = find(i, j, tmp_row, tmp_col, -chess_type);
                if(tmp > sum)
                {
                    row = tmp_row;
                    col = tmp_col;
                    sum = tmp;
                }
            }
        }
    }
}
